package com.muyu.danmo.service.impl;


import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.muyu.danmo.domain.*;
import com.muyu.danmo.domain.dto.PersonBaseInfoDTO;
import com.muyu.danmo.domain.dto.PositionInfoDTO;
import com.muyu.danmo.domain.es.PersonInfoEs;
import com.muyu.danmo.domain.mapstruct.PersonMapper;
import com.muyu.danmo.domain.vo.PersonBaseInfoVO;
import com.muyu.danmo.domain.vo.PersonInfoVO;
import com.muyu.danmo.domain.vo.PersonPositionInfoVO;
import com.muyu.danmo.domain.vo.PositionInfoVO;
import com.muyu.danmo.esMapper.PersonInfoEsRepository;
import com.muyu.danmo.mapper.*;
import com.muyu.danmo.req.DanmoInfor;
import com.muyu.danmo.service.DanmoPersonInfoService;
import com.muyu.danmo.util.ElasticScrollHelper;
import com.muyu.danmo.utils.annotation.AutoRebuildCache;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.annotations.Param;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchScrollHits;
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Service;

import java.time.Duration;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author 作者
 * @since 2025-04-11
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class DanmoPersonInfoServiceImpl extends ServiceImpl<DanmoPersonInfoMapper, DanmoPersonInfo> implements DanmoPersonInfoService {

    private final DanmoPersonInfoMapper danmoPersonInfoMapper;

    private final PersonMapper personMapper;

    private final DanmoPersonPositionMapper danmoPersonPositionMapper;

    private final DanmoAncientDynastiesMapper danmoAncientDynastiesMapper;

    private final DanmoAssociationMapper danmoAssociationMapper;

    private final DanmoAssociationTypeMapper danmoAssociationTypeMapper;

    private final DanmoInformationMassMapper danmoInformationMassMapper;

    private final DanmoInformationPositionsMapper danmoInformationPositionsMapper;

    private final DanmoInformationPhotosMapper danmoInformationPhotosMapper;

    private final DanmoInformationBarMapper danmoInformationBarMapper;

    private final DanmoPersonalPicturesMapper danmoPersonalPicturesMapper;

    private final DanmoInformationContentMapper danmoInformationContentMapper;

    private final DanmoInformationMapTitleMapper danmoInformationMapTitleMapper;

    private final DanmoInformationMapMapper danmoInformationMapMapper;

    private final DanmoInformationVideoMapper danmoInformationVideoMapper;

    private final ElasticScrollHelper elasticScrollHelper;

    @Override
//    @AutoRebuildCache(cacheName = "personBaseInf",key = "#personBaseInfoDTO.toString()",ttl = 7200)
    public List<PersonBaseInfoVO> getPersonBaseInfo(PersonBaseInfoDTO personBaseInfoDTO) {
        log.info("getPersonBaseInfo---start");
        List<PersonInfoEs> data = elasticScrollHelper.scrollQuery(
                "v_danmo_person_info_all",
                120_000L,
                10000,
                PersonInfoEs.class,
                boolQuery -> {
                    if(null != personBaseInfoDTO.getAssociationId()){
                        boolQuery.must(QueryBuilders.termQuery("associationId", personBaseInfoDTO.getAssociationId()));
                    }
                    if(null != personBaseInfoDTO.getAssociationTypeId()){
                        boolQuery.must(QueryBuilders.termQuery("associationTypeId", personBaseInfoDTO.getAssociationTypeId()));
                    }
                    if(null != personBaseInfoDTO.getPositions()){
                        boolQuery.must(QueryBuilders.termQuery("positions", personBaseInfoDTO.getPositions()));
                    }
                    if(StrUtil.isNotEmpty(personBaseInfoDTO.getYear())){
                        boolQuery.must(QueryBuilders.termQuery("year.keyword", personBaseInfoDTO.getYear()));
                    }
                    if(StrUtil.isNotEmpty(personBaseInfoDTO.getName())){
                        boolQuery.must(QueryBuilders.wildcardQuery("name.keyword",  "*" + personBaseInfoDTO.getName() + "*"));
                    }
                    if(StrUtil.isNotEmpty(personBaseInfoDTO.getAddressEntry())){
                        boolQuery.must(QueryBuilders.termQuery("addressEntry.keyword", personBaseInfoDTO.getAddressEntry()));
                    }
                    if(StrUtil.isNotEmpty(personBaseInfoDTO.getAddressCity())){
                        boolQuery.must(QueryBuilders.termQuery("addressCity.keyword", personBaseInfoDTO.getAddressCity()));
                    }
                    if(StrUtil.isNotEmpty(personBaseInfoDTO.getAddressCounty())){
                        boolQuery.must(QueryBuilders.termQuery("addressCounty.keyword", personBaseInfoDTO.getAddressCounty()));
                    }
                    if(null != personBaseInfoDTO.getSeveral()){
                        boolQuery.must(QueryBuilders.termQuery("several", personBaseInfoDTO.getSeveral()));
                    }
                    if(null != personBaseInfoDTO.getMassId()){
                        boolQuery.must(QueryBuilders.termQuery("massId", personBaseInfoDTO.getMassId()));
                    }
                    if(null != personBaseInfoDTO.getDynastiesId()){
                        boolQuery.must(QueryBuilders.termQuery("dynastiesId", personBaseInfoDTO.getDynastiesId()));
                    }
                }
        );
        log.info("getPersonBaseInfo---end:{}", data.size());
        return data.stream().map(a -> {
            PersonBaseInfoVO personBaseInfoVO = personMapper.to(a);
            personBaseInfoVO.setId(Long.valueOf(a.getPersonId()));
            return personBaseInfoVO;
        }).collect(Collectors.toList());
    }

    @Override
    public PersonInfoVO getPersonInfo(Long id) {
        DanmoPersonInfo personInfo = danmoPersonInfoMapper.selectById(id);
        PersonInfoVO personInfoVO = personMapper.to(personInfo);
        if(null == personInfoVO){
            return personInfoVO;
        }
        if(null != personInfo.getDynastiesId()){
            // 填充朝代名称
            DanmoAncientDynasties danmoAncientDynasties = danmoAncientDynastiesMapper.selectById(personInfo.getDynastiesId());
            if(null != danmoAncientDynasties){
                personInfoVO.setDynastiesName(danmoAncientDynasties.getName());
            }
        }
        // 获取关联关系
        List<DanmoPersonPosition> list = new LambdaQueryChainWrapper<>(danmoPersonPositionMapper).eq(DanmoPersonPosition::getPersonId, id).list();
        List<PersonPositionInfoVO> personPositionInfos = personMapper.to(list);
        personPositionInfos.forEach(a ->{
            if(null != a.getAssociationId()){
                DanmoAssociation one = new LambdaQueryChainWrapper<>(danmoAssociationMapper).eq(DanmoAssociation::getId, a.getAssociationId())
                        .select(DanmoAssociation::getName).one();
                a.setAssociationName(one.getName());
            }
            if(null != a.getAssociationTypeId()){
                DanmoAssociationType one = new LambdaQueryChainWrapper<>(danmoAssociationTypeMapper).eq(DanmoAssociationType::getId, a.getAssociationTypeId())
                        .select(DanmoAssociationType::getTypeName).one();
                a.setAssociationTypeName(one.getTypeName());
            }
            if (null != a.getMassId()){
                DanmoInformationMass one = new LambdaQueryChainWrapper<>(danmoInformationMassMapper).eq(DanmoInformationMass::getMassId, a.getMassId())
                        .select(DanmoInformationMass::getMassName).one();
                a.setMassName(one.getMassName());
            }
            if (null != a.getPositionId()){
                DanmoInformationPositions one = new LambdaQueryChainWrapper<>(danmoInformationPositionsMapper).eq(DanmoInformationPositions::getPositionId, a.getPositionId())
                        .select(DanmoInformationPositions::getName,DanmoInformationPositions::getGrade).one();
                a.setPositionName(one.getName());
                a.setGrade(one.getGrade());
            }
        });
        personInfoVO.setPersonPositionList(personPositionInfos);
        // 个人头像
        List<DanmoInformationPhotos> photos = new LambdaQueryChainWrapper<>(danmoInformationPhotosMapper).eq(DanmoInformationPhotos::getInformationId, id).list();
        personInfoVO.setDanmoInformationPhotosList(photos);

        // 个人简介
        DanmoInformationBar bar = new LambdaQueryChainWrapper<>(danmoInformationBarMapper).eq(DanmoInformationBar::getInformationId, id).one();
        personInfoVO.setDanmoInformationBar(bar);

        // 个人作品
        List<DanmoPersonalPictures> personalPictures = new LambdaQueryChainWrapper<>(danmoPersonalPicturesMapper).eq(DanmoPersonalPictures::getInformationId, id).list();
        personInfoVO.setDanmoPersonalPicturesList(personalPictures);

        // 个人简介
        List<DanmoInformationContent> contents = new LambdaQueryChainWrapper<>(danmoInformationContentMapper).eq(DanmoInformationContent::getInformationId, id).list();
        personInfoVO.setDanmoInformationContentList(contents);

        //视频
        List<DanmoInformationVideo> videos = new LambdaQueryChainWrapper<>(danmoInformationVideoMapper).eq(DanmoInformationVideo::getInformationId, id).list();
        personInfoVO.setDanmoInformationVideoList(videos);

        // 星图
        List<DanmoInformationMapTitle> titles = new LambdaQueryChainWrapper<>(danmoInformationMapTitleMapper).eq(DanmoInformationMapTitle::getInformationId, id).list();
        titles.forEach(a ->{
            List<DanmoInformationMap> maps = new LambdaQueryChainWrapper<>(danmoInformationMapMapper)
                    .eq(DanmoInformationMap::getMapTitleId, a.getId())
                    .eq(DanmoInformationMap::getInformationId, id)
                    .list();
            a.setDanmoInformationMapList(maps);
        });
        personInfoVO.setDanmoInformationMapTitleList(titles);
        return personInfoVO;
    }

    @Override
    @AutoRebuildCache(cacheName = "personPositionInfo",key = "#positionInfoDTO",ttl = 7200)
    public List<PositionInfoVO> getPersonPositionInfo(PositionInfoDTO positionInfoDTO) {
        return danmoPersonInfoMapper.getPersonPositionInfo(positionInfoDTO);
    }

    @Override
    public Long statistics(DanmoInformationCopy1 danmoInformationCopy1) {
        return elasticScrollHelper.countQuery("v_danmo_person_info_all", PersonInfoEs.class, query -> {
            if(null != danmoInformationCopy1.getAssociation()){
                query.must(QueryBuilders.termQuery("associationId.keyword", danmoInformationCopy1.getAssociation()));
            }
            if(null != danmoInformationCopy1.getAssociationType()){
                query.must(QueryBuilders.termQuery("associationTypeId.keyword", danmoInformationCopy1.getAssociationType()));
            }
            if(null != danmoInformationCopy1.getPositions()){
                query.must(QueryBuilders.termQuery("positions.keyword", danmoInformationCopy1.getPositions()));
            }
            if(StrUtil.isNotEmpty(danmoInformationCopy1.getAddressEntry())){
                query.must(QueryBuilders.termQuery("addressEntry.keyword", danmoInformationCopy1.getAddressEntry()));
            }
            if(StrUtil.isNotEmpty(danmoInformationCopy1.getAddressCity())){
                query.must(QueryBuilders.termQuery("addressCity.keyword", danmoInformationCopy1.getAddressCity()));
            }
        });

    }


}
